package edu.ubb.remeye.security.manager.vnc;

import javax.crypto.SecretKey;

import org.apache.mina.core.session.IoSession;
import org.codecompany.jeha.ExceptionHandler;
import org.codecompany.jeha.core.HandlerUtil;

import edu.ubb.remeye.client.settings.ClientRuntimeSettings;
import edu.ubb.remeye.communication.MessageType;
import edu.ubb.remeye.communication.message.Message;
import edu.ubb.remeye.exception.DESSecurityException;
import edu.ubb.remeye.exception.handler.RemEyeExceptionHandler;
import edu.ubb.remeye.security.manager.AbstractClientSecurity;
import edu.ubb.remeye.security.util.des.DESEncrypter;

/**
 * Server authentication class for VNC security.
 * 
 * @author Andrew Ianicicau
 *
 */
@ExceptionHandler(handler=RemEyeExceptionHandler.class)
public class ClientVNCAuthenticator extends AbstractClientSecurity {

	///////////////////////////////////////////////////////////////////////////////////
	////	ATTRIBUTES - ClientVNCAuthenticator
	///////////////////////////////////////////////////////////////////////////////////
	
	/**
	 * The key used for encryption.
	 */
	private SecretKey key;

	
	
	///////////////////////////////////////////////////////////////////////////////////
	////	CONSTRUCTORS - ClientVNCAuthenticator
	///////////////////////////////////////////////////////////////////////////////////
	
	public ClientVNCAuthenticator(IoSession session) {
		this.session = session;
	}

	
	
	///////////////////////////////////////////////////////////////////////////////////
	////	METHODS - ClientVNCAuthenticator
	///////////////////////////////////////////////////////////////////////////////////

	@Override
	public void run() {
		String clientPassword = ClientRuntimeSettings.getInstance().getClientPassword();
		authenticate(clientPassword);
		
		// setting session attribute for showing end of authentication
		authenticated();
	}
	
	/**
	 * Client side authentication algorithm.
	 * @param pass The password.
	 */
	private void authenticate(String pass) {
		if(pass != null) {
			
			// waiting for the key
			while(key == null) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// no need to do anything
				}
			}

			try {
				// encrytping the password
				String encrypted = DESEncrypter.encrypt(pass, key);
				
				// sending the password
				Message encryptedPassword = new Message(MessageType.AUTHENTICATION, encrypted.getBytes());
				session.write(encryptedPassword);
				
			} catch (DESSecurityException e) {
				HandlerUtil.handle(e);
				session.close(true);
			}
		}
	}

	/**
	 * Forwarding the key message for encryption.
	 */
	@Override
	public void forwardMessage(Message message) {
		byte[] keyBytes = message.getMessage();
		try {
			key = DESEncrypter.getSecretKeyFromBytes(keyBytes);
		} catch (DESSecurityException e) {
			HandlerUtil.handle(e);
		}
	}
}
